﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Sunny.Entity;
using Sunny.Model.RedisCache;
using Sunny.Model.RequestParam;
using Sunny.Model.Vo;
using Sunny.Service;
using Sunny.Util;
using Sunny.Util.Exception;
using Sunny.Util.Attributes;
using Sunny.Util.Enums;

namespace Sunny.Api.Controllers
{
    [ApiController]
    public class SysUserController : ControllerBase
    {
        private readonly RedisService _redisService;
        private readonly UserService _userService;
        private readonly PermissionService _permissionService;
        private readonly MenuService _menuService;
        private readonly PostService _postService;
        private readonly RoleService _roleService;
        private readonly ILogger _logger;


        public SysUserController(RedisService redisService,
            UserService userService, PermissionService permissionService, MenuService menuService,
            PostService postService,RoleService roleService,ILogger<SysUserController> logger)
        {
            _redisService = redisService;
            _userService = userService;
            _permissionService = permissionService;
            _menuService = menuService;
            _postService = postService;
            _roleService = roleService;
            _logger = logger;
        }

        #region 生成验证码
        [AllowAnonymous]
        [HttpGet]
        [Route("captchaImage")]
        public Result Captcha()
        {
            var code = CaptchaHelper.CreateRandomCode(4);
            var image = CaptchaHelper.CreateValidateImage(code);
            string uuid = Guid.NewGuid().ToString();
            string img = Convert.ToBase64String(image);
            
            _logger.LogInformation("验证码："+code);

            _redisService.Set(CommonKeyPrefix.CaptchaCode, uuid, code);

            return Result.Success(new
            {
                uuid, img
            });
        }

        #endregion

        #region 登录

        [AllowAnonymous]
        [Route("login")]
        [HttpPost]
        public async Task<Result> Login(LoginParam loginParam)
        {
            var token = await _userService.Login(loginParam);
            return Result.Success(new
            {
                token
            });
        }

        #endregion

        #region 退出
        [AllowAnonymous]
        [HttpPost("logout")]
        public Result Login()
        {
            var token = HttpContext.Request.Headers["token"].ToString();
            if (!string.IsNullOrEmpty(token))
            {
                _redisService.DeleteKey(UserKeyPrefix.Info, token);
            }

            return Result.Success();
        }

        #endregion

        #region 获取当登录信息

        [Route("getInfo")]
        [HttpGet]
        public async Task<Result> UserInfo()
        {
            SysUser user = await _userService.GetLoginUser(HttpContext.Request);
            HashSet<string> roles = await _permissionService.GetRoles(user);
            HashSet<string> permissions = await _permissionService.GetMenuPermission(user);

            return Result.Success(new
            {
                user, roles, permissions
            });
        }

        #endregion

        #region 获取树形菜单

        [Route("getRouters")]
        [HttpGet]
        public async Task<Result> GetRoutes()
        {
            SysUser user = await _userService.GetLoginUser(HttpContext.Request);
            List<RouteVo> treeMenus = await _menuService.GetTreeMenu(user);

            return Result.Success(new
            {
                data = treeMenus
            });
        }

        #endregion

        #region 获取用户列表
        [HasPermission("system:user:list")]
        [LogInfo(Title = "用户管理",BusinessType = BusinessType.Search)]
        [HttpGet(template: "system/user/list")]
        public async Task<Result> List([FromQuery] UserListParam userListParam)
        {
            (List<UserVo> users, int total) = await _userService.List(userListParam);
            return Result.Success(new
            {
                rows = users,
                total
            });
        }

        #endregion

        #region 根据ID获取用户部门和路由信息
        [HasPermission("system:user:query")]
        [HttpGet("/system/user/{userId?}")]
        public async Task<Result> UserInfo([FromRoute] long? userId)
        {
            var posts = await _postService.GetAll();
            var roles = await _roleService.GetAll();
            var sysUser = new SysUser();
            
            if(userId.HasValue)
            {
                sysUser = await _userService.GetUserById(userId.Value);
                var postIds = await _postService.GetPostIdsByUserId(userId.Value);
                var roleIds = await _roleService.GetRoleIdsByUserId(userId.Value);
                return Result.Success(new
                {
                    data = sysUser,
                    postIds,
                    roleIds,
                    posts,
                    roles
                });
            }
            else
            {
                return Result.Success(new
                {
                    data = sysUser,
                    posts,
                    roles
                });
            }
            
        }

        #endregion

        #region 修改用户
        [HasPermission("system:user:edit")]
        [LogInfo(Title = "用户管理",BusinessType = BusinessType.Update)]
        [HttpPut("/system/user")]
        public async Task<Result> Edit([FromBody]UserEditParam userEditParam)
        {
            SysUser user = new SysUser();
            user.UserId = userEditParam.UserId;
            user.Phonenumber = userEditParam.Phonenumber;
            user.Email = userEditParam.Email;
            user.UserName = userEditParam.UserName;
            
            _userService.CheckUserAllowed(user);
            bool userNameExists = await _userService.CheckUserNameExists(user);
            if(userNameExists)
            {
                throw new BusinessException(CodeMessage.UserNameExists);
            }
            bool phoneExists = await _userService.CheckPhoneExists(user);
            if(phoneExists)
            {
                throw new BusinessException(CodeMessage.UserPhoneExists);
            }
            bool emailExists = await _userService.CheckEmailExists(user);
            if(emailExists)
            {
                throw new BusinessException(CodeMessage.UserEmailExists);
            }
            
            await _userService.Update(userEditParam);
            
            return Result.Success();
        }

        #endregion

        #region 新增用户
        [HasPermission("system:user:add")]
        [LogInfo(Title = "用户管理",BusinessType = BusinessType.Insert)]
        [HttpPost("/system/user")]
        public async Task<Result> Add([FromBody]UserEditParam userEditParam)
        {
            
            SysUser user = new SysUser();
            user.UserId = -1;
            user.Phonenumber = userEditParam.Phonenumber;
            user.Email = userEditParam.Email;
            user.UserName = userEditParam.UserName;
            
            _userService.CheckUserAllowed(user);
            bool userNameExists = await _userService.CheckUserNameExists(user);
            if(userNameExists)
            {
                throw new BusinessException(CodeMessage.UserNameExists);
            }
            bool phoneExists = await _userService.CheckPhoneExists(user);
            if(phoneExists)
            {
                throw new BusinessException(CodeMessage.UserPhoneExists);
            }
            bool emailExists = await _userService.CheckEmailExists(user);
            if(emailExists)
            {
                throw new BusinessException(CodeMessage.UserEmailExists);
            }
            
            await _userService.Add(userEditParam);
            
            return Result.Success();
        }

        #endregion

        #region 删除用户
        [HasPermission("system:user:remove")]
        [LogInfo(Title = "用户管理",BusinessType = BusinessType.Delete)]
        [HttpDelete("/system/user/{userId}")]
        public async Task<Result> Delete([FromRoute]long userId)
        {
            await _userService.Delete(userId);
            return Result.Success();
        }
        #endregion

        #region 修改用户状态
        [HasPermission("system:user:edit")]
        [LogInfo(Title = "用户管理",BusinessType = BusinessType.Update)]
        [HttpPut("system/user/changeStatus")]
        public async Task<Result> ChangeStatus([FromBody]UserChangeStatusParam userChangeStatusParam)
        {
            await _userService.ChangeStatus(userChangeStatusParam.UserId,userChangeStatusParam.Status);
            return Result.Success();
        }
        #endregion

        #region 重置用户密码
        [HasPermission("system:user:resetPwd")]
        [HttpPut("system/user/resetPwd")]
        public async Task<Result> ResetPwd([FromBody]UserResetPwdParam param)
        {
            await _userService.ResetPwd(param);
            return Result.Success(param);
        }
        #endregion

        #region 获取用户信息和全部角色

        [HttpGet("system/user/authRole/{userId}")]
        public async Task<Result> AuthRole([FromRoute]long userId)
        {
            AuthRoleVo authRoleVo =  await _userService.AuthRole(userId);
            return Result.Success(authRoleVo);
        }
        #endregion

        #region 给用户设置角色
        [HasPermission("system:user:edit")]
        [LogInfo(Title = "用户管理",BusinessType = BusinessType.Update)]
        [HttpPut("/system/user/authRole")]
        public async Task<Result> SetRole([FromBody]UserSetRoleParam param)
        {
            await _userService.SetRole(param);
            return Result.Success();
        }
        #endregion

        #region 获取当前用户信息

        [HttpGet("system/user/profile")]
        public async Task<Result> Profile()
        {
            UserVo userVo = await _userService.GetProfile();
            return Result.Success(userVo);
        }

        #endregion
        
        #region 修改当前用户信息
        [LogInfo(Title = "用户管理",BusinessType = BusinessType.Update)]
        [HttpPut("system/user/profile")]
        public async Task<Result> EditProfile([FromBody]UserEditParam param)
        {
            await _userService.UpdateProfile(param);
            return Result.Success();
        }

        #endregion
        
        #region 修改当前用户密码
        [LogInfo(Title = "用户管理",BusinessType = BusinessType.Update)]
        [HttpPut("system/user/profile/updatePwd")]
        public async Task<Result> EditProfilePassword([FromBody]UserPasswordEditParam param)
        {
            await _userService.UpdatePassword(param);
            return Result.Success();
        }

        #endregion

        
    }
}